import functools, time


# 装饰器

def log_demo_one(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)

    return wrapper


def log_demo_two(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)

        return wrapper

    return decorator


# 完整的decorator 写法
def log_no_has_args(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)

    return wrapper


def log_has_args(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)

        return wrapper

    return decorator


@log_has_args('execute')
def now():
    print('2004-6-1')


# practice

"""
请设计一个decorator，它可作用于任何函数上，并打印该函数的执行时间：
"""


def metric(fn):
    @functools.wraps(fn)
    def wrapper(*args, **kw):
        start_time = time.time()
        fn_start = fn(*args, **kw)
        end_time = time.time()
        print(f"{fn.__name__}() 执行时间: {end_time - start_time:.6f} 秒")
        return fn_start

    return wrapper


"""
请编写一个decorator，能在函数调用的前后打印出'begin call'和'end call'的日志。
"""


def log(param):
    if callable(param):
        @functools.wraps(param)
        def wrapper_no_has_args(*args, **kwargs):
            print(f'{param.__name__}() begin call')
            result = param(*args, **kwargs)
            print(f'{param.__name__}() end call')
            return result

        return wrapper_no_has_args
    else:
        def decorator(func):
            @functools.wraps(func)
            def wrapper_has_args(*args, **kwargs):
                print(f'{func.__name__}() begin {param}')
                result = func(*args, **kwargs)
                print(f'{func.__name__}() end {param}')
                return result

            return wrapper_has_args

        return decorator


@metric
def fast(x, y):
    time.sleep(0.0012)
    return x + y


@metric
def slow(x, y, z):
    time.sleep(0.1234)
    return x * y * z


@log
def print_hello_world():
    print('执行中...')


if __name__ == '__main__':
    print_hello_world()
